#include <atomic>

namespace rewine
{

class IRcObject
{
public:
    virtual unsigned long TakeRef() = 0;
    virtual unsigned long FreeRef() = 0;
    virtual unsigned long GetRefCount() const = 0;

protected:
    virtual void OnReleased() = 0;
};

class CRcObject : public IRcObject
{
protected:
    std::atomic<unsigned long> m_rc{0};

    CRcObject() {}
    virtual ~CRcObject() {}

    virtual void OnReleased() override {
        delete this;
    }

public:

    unsigned long TakeRef() {
        auto rc = m_rc.fetch_add(1) + 1;
        return rc;
    }

    unsigned long FreeRef() {
        auto rc = m_rc.fetch_sub(1) - 1;
        if (rc == 0) {
            OnReleased();
        }
        return rc;
    }

    unsigned long GetRefCount() const {
        return m_rc.load();
    }
};

} // namespace rewine
